home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libcan / candraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  8.7 KB  |  442 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    candraw -
  19.  *        Draw points, lines, rectangles and texture maps onto a 
  20.  *    canvas.
  21.  *
  22.  *                Paul Haeberli - 1991
  23.  *
  24.  *    exports
  25.  *
  26.     void setalphascale(s)
  27.     void setalpha(a)
  28.     void drawapoint(c,x,y)
  29.     void drawaaline(c,x1,y1,x2,y2)
  30.     void canbeginscan(c,supersample);
  31.     void canvertex(x,y);
  32.     void cannextfacet();
  33.     void canendscan();
  34.  *
  35.  */
  36. #include "values.h"
  37. #include "math.h"
  38. #include "canvas.h"
  39. #include "texture.h"
  40. #include "izoom.h"
  41. #include "polyscan.h"
  42.  
  43. #define LINETABSIZE    (100)
  44.  
  45. float can_curalpha = 1.0;
  46. float can_curalphascale = 1.0;
  47. static unsigned char *linetab;
  48. static canvas *curcanvas;
  49. static TEXTURE *curtm;
  50. static vect curedgex, curedgey;
  51. static float sminx, smaxx;
  52. static float sminy, smaxy;
  53. static int dosupersample;
  54. static int doscanclip;
  55. static unsigned char *rowbuf;
  56. static int rowbufx, rowbuflen, curputy, lasty;
  57. static int aaxmin, aaxmax, curialph;
  58.  
  59. #define SUPERSAMPLES    (4)
  60.  
  61. void setalphascale(s)
  62. float s;
  63. {
  64.     can_curalphascale = s;
  65. }
  66.  
  67. void setalpha(a)
  68. float a;
  69. {
  70.     can_curalpha = a;
  71. }
  72.  
  73. static void initlinetab()
  74. {
  75.     int i, i3, a, b, c;
  76.     float pos, dscale;
  77.  
  78.     setfiltertype(TRIANGLE);
  79.     dscale = 1.0/filterinteg(0.0-0.5,0.0+0.5,1.0);
  80.     linetab = (unsigned char *)mymalloc(3*LINETABSIZE);
  81.     i3 = 0;
  82.     for(i=0; i<LINETABSIZE; i++) {
  83.     pos = i/(LINETABSIZE-1.0);
  84.     a = round(255.0*dscale*filterinteg(pos-2.0,pos-1.0,1.0));
  85.     b = round(255.0*dscale*filterinteg(pos-1.0,pos+0.0,1.0));
  86.     c = round(255.0*dscale*filterinteg(pos+0.0,pos+1.0,1.0));
  87.     linetab[i3+2] = a;
  88.     linetab[i3+1] = b;
  89.     linetab[i3+0] = c;
  90.     i3 += 3;
  91.     }
  92. }
  93.  
  94. /*
  95.  *    drawpoint -
  96.  *        draw an antialiased point at the specified position
  97.  *    with the current color and alpha
  98.  *
  99.  */
  100. void drawapoint(c,x,y)
  101. canvas *c;
  102. float x, y;
  103. {
  104.     float fx, fy;
  105.     int doclip;
  106.     short ix, iy, a;
  107.     unsigned long *d;
  108.     rct brect;
  109.     unsigned char abuf[2];
  110.  
  111.     if(!blendrow)
  112.     setblend(BLEND_RGB);
  113.     ix = ffloor(x);
  114.     iy = ffloor(y);
  115.     if(ix<0 || iy<0 || ix>=c->xsize-2 || iy>=c->ysize-2)
  116.     doclip = 1;
  117.     else
  118.     doclip = 0;
  119.     fx = x-ix;
  120.     fy = y-iy;
  121.     a = 255.0*can_curalpha*can_curalphascale;
  122.     brect.xmin = ix;
  123.     brect.xmax = ix+1;
  124.     brect.ymin = iy;
  125.     brect.ymax = iy+1;
  126.     saverect(c,&brect);
  127.     abuf[0] = (a*(1.0-fx)*(1.0-fy));
  128.     abuf[1] = (a*fx*(1.0-fy));
  129.     blendrow(c,abuf,ix,iy,2,doclip);
  130.     abuf[0] = (a*(1.0-fx)*fy);
  131.     abuf[1] = (a*fx*fy);
  132.     blendrow(c,abuf,ix,iy+1,2,doclip);
  133.     markdirty(c,&brect,1);
  134. }
  135.  
  136. static int nearedge(c,x,y)
  137. canvas *c;
  138. float x, y;
  139. {
  140.     if(x<2 || y<2)
  141.     return 1;
  142.     if(x>c->xsize-3 || y>c->ysize-3)
  143.     return 1;
  144.     return 0;
  145. }
  146.  
  147. void drawaaline(c,x1,y1,x2,y2)
  148. canvas *c;
  149. float x1,y1,x2,y2;
  150. {
  151.     float dx, dy, temp;
  152.     float xmin, xmax, ymin, ymax, fy, dfy;
  153.     int xs, xf, iy;
  154.     short a;
  155.     unsigned long *data;
  156.     unsigned char *wptr;
  157.     rct brect;
  158.     int doclip;
  159.     unsigned char abuf[3];
  160.  
  161.     if(nearedge(c,x1,y1) || nearedge(c,x2,y2))
  162.     doclip = 1;
  163.     else
  164.     doclip = 0;
  165.     if(!linetab)
  166.     initlinetab();
  167.     if(!blendrow)
  168.     setblend(BLEND_RGB);
  169.     a = 256.0*can_curalpha*can_curalphascale;
  170.     dx = x2-x1;
  171.     if(dx<0.0) {
  172.     xmin = x2;
  173.     xmax = x1;
  174.     dx = -dx;
  175.     } else {
  176.     xmin = x1;
  177.     xmax = x2;
  178.     }
  179.     dy = y2-y1;
  180.     if(dy<0.0) {
  181.     ymin = y2;
  182.     ymax = y1;
  183.     dy = -dy;
  184.     } else {
  185.     ymin = y1;
  186.     ymax = y2;
  187.     }
  188.     if(dx<0.01 && dy<0.01)
  189.      return;
  190.     brect.xmin = xmin-1;
  191.     brect.xmax = xmax+1;
  192.     brect.ymin = ymin-1;
  193.     brect.ymax = ymax+1;
  194.     saverect(c,&brect);
  195.     if(dx>dy) {            /* sorta horizonal line */
  196.     if(x1>x2) {
  197.         temp = x1;
  198.         x1 = x2;
  199.         x2 = temp;
  200.         temp = y1;
  201.         y1 = y2;
  202.         y2 = temp;
  203.     }
  204.     xs = ffloor(x1+0.5);
  205.     xf = ffloor(x2+0.5);
  206.     dfy = (y2-y1)/(x2-x1);
  207.     fy = y1+(x1-xs)*dfy;
  208.     data = c->data;
  209.     while(xs<=xf) { 
  210.         iy = ffloor(fy);
  211.         wptr = linetab+(3*(int)((LINETABSIZE-1)*(fy-iy)));
  212.         abuf[0] = (a*wptr[0])>>8;
  213.         abuf[1] = (a*wptr[1])>>8;
  214.         abuf[2] = (a*wptr[2])>>8;
  215.         blendcol(c,abuf,xs,iy,3,doclip);
  216.         fy += dfy;
  217.         xs++;
  218.     }
  219.     } else {            /* sorta vertical line */
  220.     if(y1>y2) {
  221.         temp = y1;
  222.         y1 = y2;
  223.         y2 = temp;
  224.         temp = x1;
  225.         x1 = x2;
  226.         x2 = temp;
  227.     }
  228.     xs = ffloor(y1+0.5);
  229.     xf = ffloor(y2+0.5);
  230.     dfy = (x2-x1)/(y2-y1);
  231.     fy = x1+(y1-xs)*dfy;
  232.     data = c->data;
  233.     while(xs<=xf) { 
  234.         iy = ffloor(fy);
  235.         wptr = linetab+(3*(int)((LINETABSIZE-1)*(fy-iy)));
  236.         abuf[0] = (a*wptr[0])>>8;
  237.         abuf[1] = (a*wptr[1])>>8;
  238.         abuf[2] = (a*wptr[2])>>8;
  239.         blendrow(c,abuf,iy,xs,3,doclip);
  240.         fy += dfy;
  241.         xs++;
  242.     }
  243.     }
  244.     markdirty(c,&brect,1);
  245. }
  246.  
  247. static gettmpos(pos,tp)
  248. vect *pos, *tp;
  249. {
  250.     tp->x = pos->x*curedgex.x+pos->y*curedgex.y+curedgex.z;
  251.     tp->y = pos->x*curedgey.x+pos->y*curedgey.y+curedgey.z;
  252. }
  253.  
  254. static void putaarow()
  255. {
  256.     int len, n;
  257.     unsigned char *buf;
  258.  
  259.     if(aaxmin != MAXINT) {
  260.     len = aaxmax-aaxmin+1;
  261.     buf = rowbuf+aaxmin;
  262.     n = len;
  263.     while(n--) {
  264.         *buf = (curialph*(*buf))/(SUPERSAMPLES*SUPERSAMPLES);
  265.         buf++;
  266.     }
  267.     blendrow(curcanvas,rowbuf+aaxmin,rowbufx+aaxmin,curputy,len,doscanclip);
  268.     }
  269. }
  270.  
  271. static void initaarow()
  272. {
  273.     bzero(rowbuf,rowbuflen);
  274.     aaxmin = MAXINT;
  275.     aaxmax = -MAXINT;
  276. }
  277.  
  278. static void fillaarow(y,x1,x2)
  279. int y, x1, x2;
  280. {
  281.     int sx1, sx2, n;
  282.     unsigned char *cptr;
  283.  
  284.     if(y<0)
  285.     return;
  286.     while(lasty<y) {
  287.     if((lasty%SUPERSAMPLES) == 0) {
  288.         curputy = lasty/SUPERSAMPLES;
  289.         if(aaxmin != MAXINT) {
  290.         putaarow();
  291.         bzero(rowbuf+aaxmin,aaxmax-aaxmin+1);
  292.         aaxmin = MAXINT;
  293.         aaxmax = -MAXINT;
  294.         curputy++;
  295.         }
  296.     }
  297.     lasty++;
  298.     }
  299.     lasty = y;
  300.     sx1 = (x1/SUPERSAMPLES)-rowbufx;
  301.     sx2 = (x2/SUPERSAMPLES)-rowbufx;
  302.     if(aaxmin>sx1)
  303.     aaxmin=sx1;
  304.     if(aaxmax<sx2)
  305.     aaxmax=sx2;
  306.     if(sx1 == sx2) {
  307.     rowbuf[sx1] += x2-x1+1;
  308.     } else {
  309.     rowbuf[sx1] += SUPERSAMPLES-(x1%SUPERSAMPLES);
  310.     rowbuf[sx2] += 1+(x2%SUPERSAMPLES);
  311.     n = sx2-sx1-1;
  312.     cptr = rowbuf+sx1+1;
  313.     while(n) {
  314.         if(n>=4) {
  315.         cptr[0] += SUPERSAMPLES;
  316.         cptr[1] += SUPERSAMPLES;
  317.         cptr[2] += SUPERSAMPLES;
  318.         cptr[3] += SUPERSAMPLES;
  319.         cptr += 4;
  320.         n -= 4;
  321.         } else {
  322.         *cptr++ += SUPERSAMPLES;
  323.         n--;
  324.         }
  325.      }
  326.     }
  327. }
  328.  
  329. void cantm(tm,edgex,edgey)
  330. TEXTURE *tm;
  331. vect *edgex, *edgey;
  332. {
  333.     curtm = tm;
  334.     if(tm) {
  335.     curedgex = *edgex;
  336.     curedgey = *edgey;
  337.     }
  338. }
  339.  
  340. static void out_span(int y, int x1, int x2)
  341. {
  342.     int n, nn, a;
  343.     unsigned char *t;
  344.     vect pos, tp, c;
  345.     double ftmx, ftmy, dtmx, dtmy;
  346.     int x, tmxsize;
  347.     unsigned char *rptr;
  348.  
  349.     n = x2-x1+1;
  350.     if(curtm) {
  351.     t = curtm->data[0];
  352.     tmxsize = curtm->xsize;
  353.     pos.x = x1;
  354.     pos.y = y;
  355.     gettmpos(&pos,&tp);
  356.     ftmx = tp.x;
  357.     ftmy = tp.y;
  358.     dtmx = curedgex.x;
  359.     dtmy = curedgey.x;
  360.     nn = n;
  361.     rptr = rowbuf;
  362.     while(nn--) {
  363.         *rptr++ = (curialph*t[((int)ftmy)*tmxsize+((int)ftmx)])>>8;
  364.         ftmx += dtmx;
  365.         ftmy += dtmy;
  366.     }
  367.     blendrow(curcanvas,rowbuf,x1,y,n,doscanclip);
  368.     } else {
  369.     if(dosupersample)
  370.         fillaarow(y,x1,x2);
  371.     else 
  372.         constblendrow(curcanvas,curialph,x1,y,n,doscanclip);
  373.     }
  374. }
  375.  
  376. void canbeginscan(c,supersample)
  377. canvas *c;
  378. int supersample;
  379. {
  380.     if(!blendrow)
  381.     setblend(BLEND_RGB);
  382.     if(curtm)
  383.     dosupersample = 0;
  384.     else
  385.     dosupersample = supersample;
  386.     curcanvas = c;
  387.     doscanclip = 0;
  388.     sminx = sminy =  MAXFLOAT;
  389.     smaxx = smaxy = -MAXFLOAT;
  390.     lasty = -100000;
  391.     scanoutspan(out_span);
  392.     scanbeginscan();
  393. }
  394.  
  395. canvertex(x,y)
  396. float x, y;
  397. {
  398.     if(nearedge(curcanvas,x,y))
  399.     doscanclip = 1;
  400.     if(dosupersample)
  401.     scanvertex(x*SUPERSAMPLES,y*SUPERSAMPLES);
  402.     else
  403.     scanvertex(x,y);
  404.     if(sminx>x) sminx = x;
  405.     if(sminy>y) sminy = y;
  406.     if(smaxx<x) smaxx = x;
  407.     if(smaxy<y) smaxy = y;
  408. }
  409.  
  410. void cannextfacet()
  411. {
  412.     scanendfacet();
  413.     scanbeginfacet();
  414. }
  415.  
  416. void canendscan()
  417. {
  418.     rct brect;
  419.     int npix;
  420.  
  421.     if(sminx==MAXFLOAT)
  422.     return;
  423.     npix = smaxx-sminx+4;
  424.     rowbuf = (unsigned char *)bufalloc(rowbuf,npix);
  425.     rowbufx = sminx-2;
  426.     rowbuflen = npix;
  427.     curialph = ffloor((255.0*can_curalpha*can_curalphascale)+0.49);
  428.     brect.xmin = sminx-1;
  429.     brect.xmax = smaxx+1;
  430.     brect.ymin = sminy-1;
  431.     brect.ymax = smaxy+1;
  432.     saverect(curcanvas,&brect);
  433.     if(dosupersample) {
  434.     initaarow();
  435.     scanendscan();
  436.     putaarow();
  437.     } else {
  438.     scanendscan();
  439.     }
  440.     markdirty(curcanvas,&brect,1);
  441. }
  442.